<template>
  <div class="app-container page-container right-side-dialog">
    <!-- 搜索条件 -->
    <div class="header-search single_line">
      <el-form ref="search_form" :model="search" :inline="true" label-width="0">
        <div class="form-area">
          <div class="search_view">
            <el-form-item>
              <el-input v-model="search.docker_name" placeholder="请选择服务器" readonly @focus="serverVisible = true"/>
            </el-form-item>
            <el-form-item>
              <el-input v-model="search.container_id" placeholder="容器ID"/>
            </el-form-item>
            <el-form-item>
              <el-input v-model="search.container_name" placeholder="容器名称"/>
            </el-form-item>
            <div class="btn-area">
              <el-button type="success" size="mini" round @click="connectServer()">连接</el-button>
              <el-button type="danger" size="mini" round @click="disconnectServer()">断开</el-button>
              <el-button type="primary" size="mini" round @click="getPaginateData()">获取列表</el-button>
              <el-button size="mini" round @click="resetData()">重置</el-button>
            </div>
          </div>
        </div>
      </el-form>
    </div>
    <!-- 表格 -->
    <div class="content_view">
      <!-- 操作按鈕 -->
      <div class="main-header">
        <el-row :gutter="20">
          <el-col :span="4" class="left">容器列表</el-col>
          <el-col :span="20" class="right">
            <el-button v-if="auth.save != -1" type="primary" size="mini" round @click="saveVisible()">新增</el-button>
          </el-col>
        </el-row>
      </div>
      <el-table ref="table" :data="paginate_data" :height="height-130" size="mini" strip>
        <el-table-column label="序号" type="index" width="60"/>
        <el-table-column label="容器ID" prop="container_id" min-width="250" align="left" show-overflow-tooltip/>
        <el-table-column label="容器名称" prop="container_name" min-width="200" align="left" show-overflow-tooltip/>
        <el-table-column label="容器状态" prop="container_state" min-width="250" align="left">
          <template slot-scope="scope">
            <el-button
              v-if="scope.row.container_state === 'running'"
              style="padding: 1px 5px;"
              type="success"
              size="mini"
              round
            >运行中
            </el-button>
            <el-button
              v-if="scope.row.container_state === 'running'"
              style="padding: 1px 5px;"
              type="success"
              size="mini"
              round
            >{{ scope.row.container_status }}
            </el-button>
            <el-button
              v-if="scope.row.container_state === 'exited'"
              style="padding: 1px 5px;"
              type="danger"
              size="mini"
              round
            >已停止
            </el-button>
            <el-button
              v-if="scope.row.container_state != 'running' && scope.row.container_state != 'exited'"
              style="padding: 1px 5px;"
              type="warning"
              size="mini"
              round
            >{{ scope.row.container_state }}
            </el-button>
          </template>
        </el-table-column>
        <el-table-column label="IP映射" min-width="180" align="left">
          <template slot-scope="scope">
            <div v-if="scope.row.ip_address.ip_address != ''">{{
                scope.row.ip_address.ip_address
              }}/{{ scope.row.ip_address.gate_way }}
            </div>
          </template>
        </el-table-column>
        <el-table-column label="端口映射" prop="container_ports" min-width="120" align="left" show-overflow-tooltip/>
        <el-table-column label="镜像名称" prop="image_name" min-width="150" align="left" show-overflow-tooltip/>
        <!-- <el-table-column label="创建时间" prop="create_time" min-width="150" align="left" /> -->
        <el-table-column label="操作" width="210" fixed="right" align="left">
          <template slot-scope="scope">
            <el-button
              v-if="scope.row.container_state ==='running' && auth.stop != -1"
              type="text"
              class="font_red"
              @click="containerStop(scope.row.container_id)"
            >停止
            </el-button>
            <el-button
              v-if="scope.row.container_state !='running' && auth.start != -1"
              type="text"
              class="font_green"
              @click="containerStart(scope.row.container_id)"
            >启动
            </el-button>
            <el-button
              v-if="auth.restart != -1"
              class="font_green"
              type="text"
              @click="containerRestart(scope.row.container_id)"
            >重启
            </el-button>
            <el-button
              v-if="auth.console != -1"
              class="font_green"
              type="text"
              @click="cmdLine(scope.row)"
            >控制台
            </el-button>
            <el-dropdown v-if="auth.remove != -1 && auth.cmd != -1 && auth.cmd != -1" trigger="click" style="margin-left: 10px;">
              <span class="el-dropdown-link">
                更多<i class="el-icon-arrow-down el-icon--right"/>
              </span>
              <el-dropdown-menu slot="dropdown">
                <el-dropdown-item
                  v-if="auth.remove != -1"
                  style="font-size: 12px;"
                  class="font_red"
                  type="text"
                  @click.native="containerRemove(scope.row.container_id,scope.row.container_name)"
                >删除
                </el-dropdown-item>
                <el-dropdown-item
                  v-if="auth.cmd != -1"
                  style="font-size: 12px;"
                  class="font_green"
                  type="text"
                  @click.native="containerCmd(scope.row.container_name)"
                >创建信息
                </el-dropdown-item>
              </el-dropdown-menu>
            </el-dropdown>
          </template>
        </el-table-column>
      </el-table>
    </div>
    <!-- 新增编辑 -->
    <el-dialog :title="edit_form.title" :visible.sync="editVisible" :close-on-click-modal="false" width="720px">
      <div class="copyContainerSelect">
        <el-select
          v-if="edit_form.type==='add'"
          v-model="copy_cr_id"
          clearable
          filterable
          placeholder="请选择复制容器"
          @change="copyContainer"
        >
          <el-option
            v-for="item in containers"
            :key="item.cr_id"
            :label="item.container_name"
            :value="item.cr_id"
          >
            <span style="float: left;font-size: 13px">{{ item.container_name }} <span
              style="color:red;"
            >#</span> {{ item.image_name }}</span>
            <span style="float: right; color: #8492a6; font-size: 13px">{{ item.docker_name }}</span>
          </el-option>
        </el-select>
      </div>
      <el-scrollbar wrap-class="vertical_scrollbar" :style="{height: height + 'px'}">
        <el-form ref="edit_form" :rules="rules" label-width="20px" :model="edit_form">
          <el-row>
            <el-col>
              <el-form-item prop="note">
                <div class="form_lable">描述</div>
                <el-input v-model="edit_form.note" type="textarea" :autosize="{ minRows: 1}" placeholder="请输入"/>
              </el-form-item>
            </el-col>
            <el-col :span="12">
              <el-form-item prop="container_name">
                <div class="form_lable">容器名称</div>
                <el-input v-model="edit_form.container_name" placeholder="请输入"/>
              </el-form-item>
            </el-col>
            <el-col :span="12">
              <el-form-item prop="image_name">
                <div class="form_lable">使用镜像</div>
                <el-select v-model="edit_form.image_name" clearable filterable placeholder="请选择">
                  <el-option
                    v-for="item in images"
                    :key="item.image_id"
                    :label="item.image_tags?item.image_tags[0]:'未知'"
                    :value="item.image_tags?item.image_tags[0]:'未知'"
                  />
                </el-select>
              </el-form-item>
            </el-col>
            <el-col :span="12">
              <el-form-item prop="bind_port">
                <div class="form_lable">端口映射</div>
                <el-input v-model="edit_form.bind_port" placeholder="暴露端口:内部端口      多个用 | 线隔开"/>
              </el-form-item>
            </el-col>
            <el-col :span="12">
              <el-form-item prop="net_work">
                <div class="form_lable">网络名称</div>
                <el-input v-model="edit_form.net_work" placeholder="请输入"/>
              </el-form-item>
            </el-col>
            <el-col :span="12">
              <el-form-item prop="ip4_address">
                <div class="form_lable">IP4地址</div>
                <el-input v-model="edit_form.ip4_address" placeholder="0.0.0.0" />
              </el-form-item>
            </el-col>
            <el-col :span="12">
              <el-form-item prop="ip6_address">
                <div class="form_lable">IP6地址</div>
                <el-input v-model="edit_form.ip6_address" placeholder="0000:0000:0000:0000:0000:0000:0000:0001"/>
              </el-form-item>
            </el-col>
            <el-col :span="12">
              <el-form-item prop="always_restart">
                <div class="form_lable">自动重启</div>
                <el-radio v-model="edit_form.always_restart" label="1">是</el-radio>
                <el-radio v-model="edit_form.always_restart" label="0">否</el-radio>
              </el-form-item>
            </el-col>
            <el-col :span="12">
              <el-form-item prop="tty">
                <div class="form_lable">分配终端并交互式启动</div>
                <el-radio v-model="edit_form.tty" label="1">是</el-radio>
                <el-radio v-model="edit_form.tty" label="0">否</el-radio>
              </el-form-item>
            </el-col>
            <el-col style="padding-left:26px;">
              <div class="add_row_class" v-if="edit_form.type==='add'">
                <el-button type="primary" style="padding: 2px 2px;" round size="mini" @click="handleAddRow">新增一行</el-button>
              </div>
              <el-table ref="table" :data="mount_path_data" @cell-dblclick="dblClickCell" style="width:650px" size="mini" strip>
                <el-table-column label="目录映射">
                  <el-table-column label="宿主机目录" prop="host_path" min-width="200" align="left" show-overflow-tooltip />
                  <el-table-column label="容器目录" prop="container_path" min-width="200" align="left" show-overflow-tooltip />
                  <el-table-column v-if="edit_form.type==='add'" fixed="right" label="操作" width="60">
                    <template slot-scope="scope">
                      <el-button @click.native.prevent="deleteRow(scope.$index, mount_path_data)" type="text" size="small">删除</el-button>
                    </template>
                  </el-table-column>
                </el-table-column>
              </el-table>
            </el-col>
            <el-col>
              <el-form-item prop="cmd">
                <div class="form_lable">cmd命令</div>
                <el-input
                  v-model="edit_form.cmd"
                  type="textarea"
                  :autosize="{ minRows: 1}"
                  placeholder="--appendonly yes|--requirepass 123456      多个用 | 线隔开"
                />
              </el-form-item>
            </el-col>
            <el-col>
              <el-form-item prop="env">
                <div class="form_lable">环境变量</div>
                <el-input
                  v-model="edit_form.env"
                  type="textarea"
                  :autosize="{ minRows: 1}"
                  placeholder="TZ=Asia/Shanghai|POSTGRESQL_ADMIN_PASSWORD=123456      多个用 | 线隔开"
                />
              </el-form-item>
            </el-col>
            <el-col>
              <el-form-item prop="working_dir">
                <div class="form_lable">工作目录</div>
                <el-input v-model="edit_form.working_dir" placeholder="/home/working"/>
              </el-form-item>
            </el-col>
          </el-row>
        </el-form>
      </el-scrollbar>
      <div v-if="edit_form.type==='add'" class="dialog-btn" style="text-align: right">
        <el-button size="mini" round @click="editVisible = false">取消</el-button>
        <el-button type="primary" size="mini" round @click="editSubmit()">保存</el-button>
      </div>
    </el-dialog>
    <!-- 选择服务器 -->
    <el-dialog
      title="选择服务器"
      :visible.sync="serverVisible"
      :close-on-click-modal="false"
      width="720px"
      class="server_view"
    >
      <el-scrollbar wrap-class="vertical_scrollbar" :style="{height: height + 'px'}">
        <SelectServer @selectServer="selectServer"/>
      </el-scrollbar>
    </el-dialog>
    <!-- 控制台 -->
    <el-dialog
      :visible.sync="commandLine"
      :close-on-click-modal="false"
      width="720px"
      class="server_view"
      @opened="openCMD" @closed="closeCMD"
    >
      <div class="consoleTitle">
        <span>{{containerTitle}}</span>
      </div>
      <el-scrollbar wrap-class="vertical_scrollbar" :style="{height: height + 'px'}">
        <Xterm :containerId="containerId"
              :containerName="containerName"
              :server-id="search.server_id"
              url="/websocket/container/cmd"
              ref="xterm"/>
      </el-scrollbar>
    </el-dialog>
  </div>
</template>
<script>
import { list, start, stop, restart, images, save, remove, cmd, detail, look } from '@/api/pajx/server/container'
import { mapState } from 'vuex'
import SelectServer from '@/components/SelectServer'
import { connect, disconnect } from '@/api/public'

import Xterm from '@/components/Xterm'

export default {
  name: 'DockerServer',
  components: { SelectServer, Xterm },
  data() {
    var validateContainer_name = (rule, value, callback) => {
      if (value === '') {
        callback(new Error('请输入镜像名称'))
      } else {
        callback()
      }
    }
    var validateImage_name = (rule, value, callback) => {
      if (value === '') {
        callback(new Error('请选择镜像'))
      } else {
        callback()
      }
    }
    return {
      height: window.innerHeight - 135,
      auth: {},
      search: {},
      paginate_data: [],
      mount_path_data:[],
      containers: [],
      copy_cr_id:'',
      images: [],
      editVisible: false,
      serverVisible: false,
      containerName:'',
      rules: {
        container_name: [
          { validator: validateContainer_name, trigger: 'blur' }
        ],
        image_name: [
          { validator: validateImage_name, trigger: 'change' }
        ]
      },
      edit_form: {
        title: '新增容器',
        type: 'add',
        server_id: '',
        container_name: '',
        image_name: '',
        bind_port: '',
        net_work: '',
        always_restart: '1',
        tty: '0',
        cmd: '',
        ip4_address: '',
        ip6_address: '',
        working_dir: '',
        mount_path: '',
        env: '',
        note: ''
      },
      commandLine: false,
      containerId: '',
      containerTitle: ''
    }
  },
  computed: {
    ...mapState({
      permission: state => state.permission.permission
    })
  },
  watch: {
    editVisible(val) {
      if (val) {
        this.edit_form.title = this.edit_form.type === 'add' ? '新增容器' : '容器创建信息'
      }
      if (!val) {
        Object.assign(this.$data.edit_form, this.$options.data().edit_form)
      }
    }
  },
  beforeMount() {
    Object.assign(this.$data, this.$store.state.container.data)
  },
  beforeDestroy() {
    this.$store.commit('commitContainerData', this.$data)
  },
  created() {
    this.permissionAuth()
  },
  methods: {
    // 获取按钮权限
    permissionAuth() {
      this.auth.save = this.permission.indexOf('/api/docker/container/save')
      this.auth.start = this.permission.indexOf('/api/docker/container/start')
      this.auth.stop = this.permission.indexOf('/api/docker/container/stop')
      this.auth.restart = this.permission.indexOf('/api/docker/container/restart')
      this.auth.remove = this.permission.indexOf('/api/docker/container/remove')
      this.auth.cmd = this.permission.indexOf('/api/docker/container/cmd')
      this.auth.console = this.permission.indexOf('/api/docker/container/console')
    },
    // 重置搜索选项
    resetData() {
      this.search = {}
    },
    // 选择服务器
    selectServer(data) {
      this.serverVisible = false
      this.search.server_id = data.server_id
      this.search.docker_name = data.docker_name
      this.edit_form.server_id = data.server_id
      // this.getPaginateData()
    },
    // 连接服务
    connectServer() {
      if (!this.search.server_id) {
        this.$notify({
          title: '提示',
          message: '请选择服务器',
          type: 'warning'
        })
        return
      }
      connect(this.search.server_id).then(response => {
        this.$notify({
          title: '成功',
          message: '连接成功',
          type: 'success'
        })
      })
    },
    // 断开服务
    disconnectServer() {
      if (!this.search.server_id) {
        this.$notify({
          title: '提示',
          message: '请选择服务器',
          type: 'warning'
        })
        return
      }
      this.$confirm('确认断开服务？', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        disconnect(this.search.server_id).then(response => {
          this.$notify({
            title: '提示',
            message: '连接已断开',
            type: 'warning'
          })
        })
        this.paginate_data = []
      }).catch(() => {
      })
    },
    // 获取列表
    getPaginateData() {
      if (!this.search.server_id) {
        this.$notify({
          title: '提示',
          message: '请选择服务器',
          type: 'warning'
        })
        return
      }
      list(this.search).then(response => {
        this.paginate_data = response.data
      })
    },
    saveVisible() {
      if (!this.search.server_id) {
        this.$notify({
          title: '提示',
          message: '请选择服务器',
          type: 'warning'
        })
        return
      }
      this.mount_path_data =[];
      this.edit_form.server_id = this.search.server_id
      look().then(res => {
        this.containers = res.data
      })
      images(this.edit_form.server_id).then(res => {
        this.images = res.data
        this.editVisible = true
      })
    },
    copyContainer(cr_id) {
      if(!cr_id){
        this.mount_path_data = []
        this.initEditForm()
        return;
      }
      detail(cr_id).then(res =>{
        this.feedback(res);
      })
      this.edit_form.type = 'add'
    },
    feedback(response){
      this.editVisible = true
      this.edit_form.container_name = response.data.container_name
      this.edit_form.image_name = response.data.image_name
      this.edit_form.bind_port = response.data.bind_port
      this.edit_form.net_work = response.data.net_work
      this.edit_form.always_restart = response.data.always_restart
      this.edit_form.tty = response.data.tty
      this.edit_form.cmd = response.data.cmd
      this.edit_form.ip4_address = response.data.ip4_address
      this.edit_form.ip6_address = response.data.ip6_address
      this.edit_form.working_dir = response.data.working_dir
      this.edit_form.mount_path = response.data.mount_path
      this.edit_form.env = response.data.env
      this.edit_form.note = response.data.note
      this.edit_form.server_id = this.search.server_id
      this.buildMountPath(response.data.mount_path);
    },
    initEditForm(){
      this.edit_form.server_id = this.search.server_id
      this.edit_form.container_name = ''
      this.edit_form.image_name = ''
      this.edit_form.bind_port = ''
      this.edit_form.net_work = ''
      this.edit_form.always_restart = '1'
      this.edit_form.tty = '0'
      this.edit_form.cmd = ''
      this.edit_form.ip4_address = ''
      this.edit_form.ip6_address = ''
      this.edit_form.working_dir = ''
      this.edit_form.mount_path = []
      this.edit_form.env = ''
      this.edit_form.note = ''
    },
    //构建映射表格数据
    buildMountPath(mount_path){
      this.mount_path_data =[];
      if(mount_path){
        var mountPaths = mount_path.split('|');
        for(var i=0;i<mountPaths.length;i++){
          var paths = mountPaths[i].split(':');
          this.mount_path_data.push({"host_path":paths[0],"container_path":paths[1]});
        }
      }
    },
    //新增一行
    handleAddRow(){
      if (!this.mount_path_data) {
        this.mount_path_data = new Array();
      }
      let obj = {};
      obj.host_path = "";
      obj.container_path = "";
      this.mount_path_data.push(obj);
    },
    //删除一行
    deleteRow(index, rows) {
      rows.splice(index, 1);
    },
    //双击单元格
    dblClickCell(row, column, cell, event){
      if(this.edit_form.type != 'add'){
        return;
      }
      if(column.label === '操作'){
        return;
      }
      event.target.innerHTML = "";
      let cellInput = document.createElement("input");
      cellInput.value = "";
      if(column.property === 'host_path' && row.host_path){
        cellInput.value = row.host_path;
      }
      if(column.property === 'container_path' && row.container_path){
        cellInput.value = row.container_path;
      }
      cellInput.setAttribute("type", "text");
      cellInput.style.width = "100%";
      cellInput.style.height = "100%";
      cell.appendChild(cellInput);
      var that = this;
      cellInput.onblur = function() {
        cell.removeChild(cellInput);
        if(column.property === 'host_path'){
          row.host_path = cellInput.value;
        }
        if(column.property === 'container_path'){
          row.container_path = cellInput.value;
        }
        event.target.innerHTML = cellInput.value;
        if(!cellInput.value){
          that.$notify({
            title: '提示',
            message: '请输入正确路径',
            type: 'warning'
          })
          return;
        }
      };
    },
    //获取映射目录表格数据
    getMountPathTableData(){
      if(this.mount_path_data){
        var pathData = this.mount_path_data;
        var resultData='';
        for(var i=0,length=pathData.length;i<length;i++){
          if(!pathData[i].host_path||!pathData[i].container_path){
            return '';
          }
          if(i===length-1){
            resultData+=(pathData[i].host_path+':'+pathData[i].container_path);
          }else{
            resultData+=(pathData[i].host_path+':'+pathData[i].container_path+'|');
          }
        }
        return resultData;
      }
    },
    // 新增编辑
    editSubmit() {
      if (this.edit_form.type === 'add') {
        var pathData = this.getMountPathTableData();
        if(!pathData){
          this.$notify({
            title: '提示',
            message: '目录映射错误',
            type: 'warning'
          })
          return;
        }
        this.edit_form.mount_path = pathData;
        this.$refs['edit_form'].validate((valid) => {
          if (valid) {
            save(this.edit_form).then(response => {
              this.editVisible = false
              this.$message({
                message: '操作成功',
                type: 'success'
              })
              this.getPaginateData()
            })
          } else {
            return false
          }
        })
      }
    },
    containerRemove(container_id, container_name) {
      if (!this.search.server_id) {
        this.$notify({
          title: '提示',
          message: '请选择服务器',
          type: 'warning'
        })
        return
      }
      this.$confirm('确认删除容器？', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        remove(this.search.server_id, container_id, container_name).then(res => {
          this.$notify({
            title: '消息',
            message: '删除成功',
            type: 'success'
          })
          this.getPaginateData()
        })
      }).catch(() => {
      })
    },
    // 回显
    containerCmd(container_name) {
      if (!this.search.server_id) {
        this.$notify({
          title: '提示',
          message: '请选择服务器',
          type: 'warning'
        })
        return
      }
      cmd(this.edit_form.server_id,container_name).then(response => {
        this.feedback(response);
      })
      this.edit_form.type = 'edit'
    },
    containerStop(container_id) {
      this.$confirm('确认停止容器？', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        stop({ 'container_id': container_id, 'server_id': this.search.server_id }).then(response => {
          this.$notify({
            title: '消息',
            message: '停止成功',
            type: 'success'
          })
          this.getPaginateData()
        })
      }).catch(() => {
      })
    },
    containerStart(container_id) {
      this.$confirm('确认启动容器？', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        start({ 'container_id': container_id, 'server_id': this.search.server_id }).then(response => {
          this.$notify({
            title: '消息',
            message: '启动成功',
            type: 'success'
          })
          this.getPaginateData()
        })
      }).catch(() => {
      })
    },
    containerRestart(container_id) {
      this.$confirm('确认启动容器？', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        restart({ 'container_id': container_id, 'server_id': this.search.server_id }).then(response => {
          this.$notify({
            title: '消息',
            message: '重启成功',
            type: 'success'
          })
          this.getPaginateData()
        })
      }).catch(() => {
      })
    },
    cmdLine(row) {
      this.containerId = row.container_id
      this.containerName = row.container_name
      this.containerTitle = "容器名称："+row.container_name
      this.commandLine = true
    },
    openCMD() {
      // this.$refs.xterm.websocketConnect()
    },
    closeCMD() {
      // this.$refs.xterm.closeWebSocket()
    }
  }
}
</script>
<style lang="scss">

.font_red {
  color: #FF5722;
}

.font_green {
  color: #3399ff;
}

.el-dropdown-link {
  font-size: 12px;
}

.copyContainerSelect {
  position: absolute;
  left: 100px;
  top: 6px;
  width: 520px;
}

.add_row_class{
  position: relative;
  z-index: 9999999;
  top: 25px;
  left: 70px;
  width: 70px;
}

.consoleTitle{
  position: absolute;
  left: 20px;
  top: 16px;
}

</style>
